

 /*
 This file '_slider' is part of Firebird Integrated Solution 1.0

 Copyright (c) 2015 Lincong

 Contact:  
        Email: lincong1987@gmail.com

        QQ: 159257119
 
 See Usage at http://www.jplatformx.com/firebird

 Create date: 2015-07-14 04:46
 */

 (function ($, undefined) {

// number of pages in a slider
// (how many times can you page up/down to go through the whole range)
     var numPages = 5;

     $.widget("ui.slider", $.ui.mouse, {
         version: "1.9.2",
         widgetEventPrefix: "slide",

         options: {
             animate: false,
             distance: 0,
             max: 100,
             min: 0,
             orientation: "horizontal",
             range: false,
             step: 1,
             value: 0,
             values: null
         },

         _create: function () {
             var i, handleCount,
                 o = this.options,
                 existingHandles = this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),
                 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
                 handles = [];

             this._keySliding = false;
             this._mouseSliding = false;
             this._animateOff = true;
             this._handleIndex = null;
             this._detectOrientation();
             this._mouseInit();

             this.element
                 .addClass("ui-slider" +
                 " ui-slider-" + this.orientation +
                 " ui-widget" +
                 " ui-widget-content" +
                 " ui-corner-all" +
                 ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ));

             this.range = $([]);

             if (o.range) {
                 if (o.range === true) {
                     if (!o.values) {
                         o.values = [this._valueMin(), this._valueMin()];
                     }
                     if (o.values.length && o.values.length !== 2) {
                         o.values = [o.values[0], o.values[0]];
                     }
                 }

                 this.range = $("<div></div>")
                     .appendTo(this.element)
                     .addClass("ui-slider-range" +
                         // note: this isn't the most fittingly semantic framework class for this element,
                         // but worked best visually with a variety of themes
                     " ui-widget-header" +
                     ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ));
             }

             handleCount = ( o.values && o.values.length ) || 1;

             for (i = existingHandles.length; i < handleCount; i++) {
                 handles.push(handle);
             }

             this.handles = existingHandles.add($(handles.join("")).appendTo(this.element));

             this.handle = this.handles.eq(0);

             this.handles.add(this.range).filter("a")
                 .click(function (event) {
                     event.preventDefault();
                 })
                 .mouseenter(function () {
                     if (!o.disabled) {
                         $(this).addClass("ui-state-hover");
                     }
                 })
                 .mouseleave(function () {
                     $(this).removeClass("ui-state-hover");
                 })
                 .focus(function () {
                     if (!o.disabled) {
                         $(".ui-slider .ui-state-focus").removeClass("ui-state-focus");
                         $(this).addClass("ui-state-focus");
                     } else {
                         $(this).blur();
                     }
                 })
                 .blur(function () {
                     $(this).removeClass("ui-state-focus");
                 });

             this.handles.each(function (i) {
                 $(this).data("ui-slider-handle-index", i);
             });

             this._on(this.handles, {
                 keydown: function (event) {
                     var allowed, curVal, newVal, step,
                         index = $(event.target).data("ui-slider-handle-index");

                     switch (event.keyCode) {
                         case $.ui.keyCode.HOME:
                         case $.ui.keyCode.END:
                         case $.ui.keyCode.PAGE_UP:
                         case $.ui.keyCode.PAGE_DOWN:
                         case $.ui.keyCode.UP:
                         case $.ui.keyCode.RIGHT:
                         case $.ui.keyCode.DOWN:
                         case $.ui.keyCode.LEFT:
                             event.preventDefault();
                             if (!this._keySliding) {
                                 this._keySliding = true;
                                 $(event.target).addClass("ui-state-active");
                                 allowed = this._start(event, index);
                                 if (allowed === false) {
                                     return;
                                 }
                             }
                             break;
                     }

                     step = this.options.step;
                     if (this.options.values && this.options.values.length) {
                         curVal = newVal = this.values(index);
                     } else {
                         curVal = newVal = this.value();
                     }

                     switch (event.keyCode) {
                         case $.ui.keyCode.HOME:
                             newVal = this._valueMin();
                             break;
                         case $.ui.keyCode.END:
                             newVal = this._valueMax();
                             break;
                         case $.ui.keyCode.PAGE_UP:
                             newVal = this._trimAlignValue(curVal + ( (this._valueMax() - this._valueMin()) / numPages ));
                             break;
                         case $.ui.keyCode.PAGE_DOWN:
                             newVal = this._trimAlignValue(curVal - ( (this._valueMax() - this._valueMin()) / numPages ));
                             break;
                         case $.ui.keyCode.UP:
                         case $.ui.keyCode.RIGHT:
                             if (curVal === this._valueMax()) {
                                 return;
                             }
                             newVal = this._trimAlignValue(curVal + step);
                             break;
                         case $.ui.keyCode.DOWN:
                         case $.ui.keyCode.LEFT:
                             if (curVal === this._valueMin()) {
                                 return;
                             }
                             newVal = this._trimAlignValue(curVal - step);
                             break;
                     }

                     this._slide(event, index, newVal);
                 },
                 keyup: function (event) {
                     var index = $(event.target).data("ui-slider-handle-index");

                     if (this._keySliding) {
                         this._keySliding = false;
                         this._stop(event, index);
                         this._change(event, index);
                         $(event.target).removeClass("ui-state-active");
                     }
                 }
             });

             this._refreshValue();

             this._animateOff = false;
         },

         _destroy: function () {
             this.handles.remove();
             this.range.remove();

             this.element
                 .removeClass("ui-slider" +
                 " ui-slider-horizontal" +
                 " ui-slider-vertical" +
                 " ui-slider-disabled" +
                 " ui-widget" +
                 " ui-widget-content" +
                 " ui-corner-all");

             this._mouseDestroy();
         },

         _mouseCapture: function (event) {
             var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
                 that = this,
                 o = this.options;

             if (o.disabled) {
                 return false;
             }

             this.elementSize = {
                 width: this.element.outerWidth(),
                 height: this.element.outerHeight()
             };
             this.elementOffset = this.element.offset();

             position = {x: event.pageX, y: event.pageY};
             normValue = this._normValueFromMouse(position);
             distance = this._valueMax() - this._valueMin() + 1;
             this.handles.each(function (i) {
                 var thisDistance = Math.abs(normValue - that.values(i));
                 if (distance > thisDistance) {
                     distance = thisDistance;
                     closestHandle = $(this);
                     index = i;
                 }
             });

             // workaround for bug #3736 (if both handles of a range are at 0,
             // the first is always used as the one with least distance,
             // and moving it is obviously prevented by preventing negative ranges)
             if (o.range === true && this.values(1) === o.min) {
                 index += 1;
                 closestHandle = $(this.handles[index]);
             }

             allowed = this._start(event, index);
             if (allowed === false) {
                 return false;
             }
             this._mouseSliding = true;

             this._handleIndex = index;

             closestHandle
                 .addClass("ui-state-active")
                 .focus();

             offset = closestHandle.offset();
             mouseOverHandle = !$(event.target).parents().andSelf().is(".ui-slider-handle");
             this._clickOffset = mouseOverHandle ? {left: 0, top: 0} : {
                 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
                 top: event.pageY - offset.top -
                 ( closestHandle.height() / 2 ) -
                 ( parseInt(closestHandle.css("borderTopWidth"), 10) || 0 ) -
                 ( parseInt(closestHandle.css("borderBottomWidth"), 10) || 0) +
                 ( parseInt(closestHandle.css("marginTop"), 10) || 0)
             };

             if (!this.handles.hasClass("ui-state-hover")) {
                 this._slide(event, index, normValue);
             }
             this._animateOff = true;
             return true;
         },

         _mouseStart: function () {
             return true;
         },

         _mouseDrag: function (event) {
             var position = {x: event.pageX, y: event.pageY},
                 normValue = this._normValueFromMouse(position);

             this._slide(event, this._handleIndex, normValue);

             return false;
         },

         _mouseStop: function (event) {
             this.handles.removeClass("ui-state-active");
             this._mouseSliding = false;

             this._stop(event, this._handleIndex);
             this._change(event, this._handleIndex);

             this._handleIndex = null;
             this._clickOffset = null;
             this._animateOff = false;

             return false;
         },

         _detectOrientation: function () {
             this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
         },

         _normValueFromMouse: function (position) {
             var pixelTotal,
                 pixelMouse,
                 percentMouse,
                 valueTotal,
                 valueMouse;

             if (this.orientation === "horizontal") {
                 pixelTotal = this.elementSize.width;
                 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
             } else {
                 pixelTotal = this.elementSize.height;
                 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
             }

             percentMouse = ( pixelMouse / pixelTotal );
             if (percentMouse > 1) {
                 percentMouse = 1;
             }
             if (percentMouse < 0) {
                 percentMouse = 0;
             }
             if (this.orientation === "vertical") {
                 percentMouse = 1 - percentMouse;
             }

             valueTotal = this._valueMax() - this._valueMin();
             valueMouse = this._valueMin() + percentMouse * valueTotal;

             return this._trimAlignValue(valueMouse);
         },

         _start: function (event, index) {
             var uiHash = {
                 handle: this.handles[index],
                 value: this.value()
             };
             if (this.options.values && this.options.values.length) {
                 uiHash.value = this.values(index);
                 uiHash.values = this.values();
             }
             return this._trigger("start", event, uiHash);
         },

         _slide: function (event, index, newVal) {
             var otherVal,
                 newValues,
                 allowed;

             if (this.options.values && this.options.values.length) {
                 otherVal = this.values(index ? 0 : 1);

                 if (( this.options.values.length === 2 && this.options.range === true ) &&
                     ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
                 ) {
                     newVal = otherVal;
                 }

                 if (newVal !== this.values(index)) {
                     newValues = this.values();
                     newValues[index] = newVal;
                     // A slide can be canceled by returning false from the slide callback
                     allowed = this._trigger("slide", event, {
                         handle: this.handles[index],
                         value: newVal,
                         values: newValues
                     });
                     otherVal = this.values(index ? 0 : 1);
                     if (allowed !== false) {
                         this.values(index, newVal, true);
                     }
                 }
             } else {
                 if (newVal !== this.value()) {
                     // A slide can be canceled by returning false from the slide callback
                     allowed = this._trigger("slide", event, {
                         handle: this.handles[index],
                         value: newVal
                     });
                     if (allowed !== false) {
                         this.value(newVal);
                     }
                 }
             }
         },

         _stop: function (event, index) {
             var uiHash = {
                 handle: this.handles[index],
                 value: this.value()
             };
             if (this.options.values && this.options.values.length) {
                 uiHash.value = this.values(index);
                 uiHash.values = this.values();
             }

             this._trigger("stop", event, uiHash);
         },

         _change: function (event, index) {
             if (!this._keySliding && !this._mouseSliding) {
                 var uiHash = {
                     handle: this.handles[index],
                     value: this.value()
                 };
                 if (this.options.values && this.options.values.length) {
                     uiHash.value = this.values(index);
                     uiHash.values = this.values();
                 }

                 this._trigger("change", event, uiHash);
             }
         },

         value: function (newValue) {
             if (arguments.length) {
                 this.options.value = this._trimAlignValue(newValue);
                 this._refreshValue();
                 this._change(null, 0);
                 return;
             }

             return this._value();
         },

         values: function (index, newValue) {
             var vals,
                 newValues,
                 i;

             if (arguments.length > 1) {
                 this.options.values[index] = this._trimAlignValue(newValue);
                 this._refreshValue();
                 this._change(null, index);
                 return;
             }

             if (arguments.length) {
                 if ($.isArray(arguments[0])) {
                     vals = this.options.values;
                     newValues = arguments[0];
                     for (i = 0; i < vals.length; i += 1) {
                         vals[i] = this._trimAlignValue(newValues[i]);
                         this._change(null, i);
                     }
                     this._refreshValue();
                 } else {
                     if (this.options.values && this.options.values.length) {
                         return this._values(index);
                     } else {
                         return this.value();
                     }
                 }
             } else {
                 return this._values();
             }
         },

         _setOption: function (key, value) {
             var i,
                 valsLength = 0;

             if ($.isArray(this.options.values)) {
                 valsLength = this.options.values.length;
             }

             $.Widget.prototype._setOption.apply(this, arguments);

             switch (key) {
                 case "disabled":
                     if (value) {
                         this.handles.filter(".ui-state-focus").blur();
                         this.handles.removeClass("ui-state-hover");
                         this.handles.prop("disabled", true);
                         this.element.addClass("ui-disabled");
                     } else {
                         this.handles.prop("disabled", false);
                         this.element.removeClass("ui-disabled");
                     }
                     break;
                 case "orientation":
                     this._detectOrientation();
                     this.element
                         .removeClass("ui-slider-horizontal ui-slider-vertical")
                         .addClass("ui-slider-" + this.orientation);
                     this._refreshValue();
                     break;
                 case "value":
                     this._animateOff = true;
                     this._refreshValue();
                     this._change(null, 0);
                     this._animateOff = false;
                     break;
                 case "values":
                     this._animateOff = true;
                     this._refreshValue();
                     for (i = 0; i < valsLength; i += 1) {
                         this._change(null, i);
                     }
                     this._animateOff = false;
                     break;
                 case "min":
                 case "max":
                     this._animateOff = true;
                     this._refreshValue();
                     this._animateOff = false;
                     break;
             }
         },

         //internal value getter
         // _value() returns value trimmed by min and max, aligned by step
         _value: function () {
             var val = this.options.value;
             val = this._trimAlignValue(val);

             return val;
         },

         //internal values getter
         // _values() returns array of values trimmed by min and max, aligned by step
         // _values( index ) returns single value trimmed by min and max, aligned by step
         _values: function (index) {
             var val,
                 vals,
                 i;

             if (arguments.length) {
                 val = this.options.values[index];
                 val = this._trimAlignValue(val);

                 return val;
             } else {
                 // .slice() creates a copy of the array
                 // this copy gets trimmed by min and max and then returned
                 vals = this.options.values.slice();
                 for (i = 0; i < vals.length; i += 1) {
                     vals[i] = this._trimAlignValue(vals[i]);
                 }

                 return vals;
             }
         },

         // returns the step-aligned value that val is closest to, between (inclusive) min and max
         _trimAlignValue: function (val) {
             if (val <= this._valueMin()) {
                 return this._valueMin();
             }
             if (val >= this._valueMax()) {
                 return this._valueMax();
             }
             var step = ( this.options.step > 0 ) ? this.options.step : 1,
                 valModStep = (val - this._valueMin()) % step,
                 alignValue = val - valModStep;

             if (Math.abs(valModStep) * 2 >= step) {
                 alignValue += ( valModStep > 0 ) ? step : ( -step );
             }

             // Since JavaScript has problems with large floats, round
             // the final value to 5 digits after the decimal point (see #4124)
             return parseFloat(alignValue.toFixed(5));
         },

         _valueMin: function () {
             return this.options.min;
         },

         _valueMax: function () {
             return this.options.max;
         },

         _refreshValue: function () {
             var lastValPercent, valPercent, value, valueMin, valueMax,
                 oRange = this.options.range,
                 o = this.options,
                 that = this,
                 animate = ( !this._animateOff ) ? o.animate : false,
                 _set = {};

             if (this.options.values && this.options.values.length) {
                 this.handles.each(function (i) {
                     valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
                     _set[that.orientation === "horizontal" ? "left" : "bottom"] = valPercent + "%";
                     $(this).stop(1, 1)[animate ? "animate" : "css"](_set, o.animate);
                     if (that.options.range === true) {
                         if (that.orientation === "horizontal") {
                             if (i === 0) {
                                 that.range.stop(1, 1)[animate ? "animate" : "css"]({left: valPercent + "%"}, o.animate);
                             }
                             if (i === 1) {
                                 that.range[animate ? "animate" : "css"]({width: ( valPercent - lastValPercent ) + "%"}, {
                                     queue: false,
                                     duration: o.animate
                                 });
                             }
                         } else {
                             if (i === 0) {
                                 that.range.stop(1, 1)[animate ? "animate" : "css"]({bottom: ( valPercent ) + "%"}, o.animate);
                             }
                             if (i === 1) {
                                 that.range[animate ? "animate" : "css"]({height: ( valPercent - lastValPercent ) + "%"}, {
                                     queue: false,
                                     duration: o.animate
                                 });
                             }
                         }
                     }
                     lastValPercent = valPercent;
                 });
             } else {
                 value = this.value();
                 valueMin = this._valueMin();
                 valueMax = this._valueMax();
                 valPercent = ( valueMax !== valueMin ) ?
                 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
                     0;
                 _set[this.orientation === "horizontal" ? "left" : "bottom"] = valPercent + "%";
                 this.handle.stop(1, 1)[animate ? "animate" : "css"](_set, o.animate);

                 if (oRange === "min" && this.orientation === "horizontal") {
                     this.range.stop(1, 1)[animate ? "animate" : "css"]({width: valPercent + "%"}, o.animate);
                 }
                 if (oRange === "max" && this.orientation === "horizontal") {
                     this.range[animate ? "animate" : "css"]({width: ( 100 - valPercent ) + "%"}, {
                         queue: false,
                         duration: o.animate
                     });
                 }
                 if (oRange === "min" && this.orientation === "vertical") {
                     this.range.stop(1, 1)[animate ? "animate" : "css"]({height: valPercent + "%"}, o.animate);
                 }
                 if (oRange === "max" && this.orientation === "vertical") {
                     this.range[animate ? "animate" : "css"]({height: ( 100 - valPercent ) + "%"}, {
                         queue: false,
                         duration: o.animate
                     });
                 }
             }
         }

     });

 }(jQuery));